package com.job51.hro.exlog.aspect;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.job51.hro.exlog.box.Lion;
import com.job51.hro.exlog.box.PersonalMention;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.annotation.Order;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 〈在执行requestBody注解之前拓展〉<br>
 * 〈〉
 *
 * @author pengfei.ma
 * @create 2022/11/24
 * @since 1.0.0
 */
@Component
@RefreshScope
@Order(-99)
public class RequestPreAdviser extends BaseAspect implements HandlerInterceptor {

    @Value("${spring.application.name}")
    public String appName;

    @Resource
    Lion lion;

    @Resource
    PersonalMention personalMention;

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
        clearMDC();
        MDC.put(APP_NAME, appName);
        Map<String, Object> requestInfo = this.getRequest();
        if (requestInfo != null) {
            String uuid = UuidUtils.generateUuid();
            JSONObject headers = (JSONObject) requestInfo.get("headers");
            if (headers.get(GLOBAL_REQ_ID.toLowerCase()) != null) {
                MDC.put(GLOBAL_REQ_ID, (String) headers.get(GLOBAL_REQ_ID.toLowerCase()));
            } else {
                MDC.put(GLOBAL_REQ_ID, uuid);
            }
            MDC.put(REQID, uuid);
            MDC.put(URI, requestInfo.get("uri").toString());
            MDC.put(METHOD, requestInfo.get("method").toString());
            JSONObject headersJsonObj = (JSONObject) requestInfo.get("headers");
            List<String> headersAllow = Arrays.asList(lion.getPassHeader());
            Map<String, Object> headerWriter = new LinkedHashMap<>();
            for (Map.Entry<String, Object> entry : headersJsonObj.entrySet()) {
                String headerK = entry.getKey();
                Object headerV = entry.getValue();
                if (headersAllow.contains(headerK)) {
                    headerWriter.put(headerK, headerV);
                }
            }
            MDC.put(HEADERS, headerWriter.toString());
            MDC.put(PARAMS, requestInfo.get("params").toString());
            MDC.put(PERSONAL_MENTION, personalMention.outPut().toString());
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                 @Nullable Exception ex) throws Exception {
        clearMDC();
    }

    private void clearMDC() {
        MDC.remove(REQID);
        MDC.remove(GLOBAL_REQ_ID);
        MDC.remove(URI);
        MDC.remove(METHOD);
        MDC.remove(HEADERS);
        MDC.remove(PARAMS);
        MDC.remove(PERSONAL_MENTION);
    }
}
